﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2014-04-08 23:50
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using BassDrop.Core.Common.Exceptions.Cloud;
using DropNetRT.Exceptions;

namespace BassDrop.Plugins.Dropbox
{
	/// <summary>
	/// Class for helping to create proper exceptions
	/// </summary>
	public static class ExceptionHelper
	{
		/// <summary>
		/// Returns an instance of a subclass of CloudExceptionBase for the passed exception if it is a known kind,
		/// return the original exception otherwise
		/// </summary>
		/// <param name="e">the exception to convert</param>
		/// <returns></returns>
		public static Exception GetCloudException( this Exception e )
		{
			// TODO: értelmes, lokalizált üzenetek, dropboxException.Response használata üzenetekhez

			if ( e is CloudExceptionBase )
			{
				return e;
			}

			var dropboxException = e as DropboxException;

			if ( dropboxException != null )
			{
				if ( dropboxException.StatusCode != 0 )
				{
					switch ( dropboxException.StatusCode )
					{
						case System.Net.HttpStatusCode.NotFound:
							return new CloudFileNotFoundException( dropboxException.Message, dropboxException );

						case (HttpStatusCode) 429: // rate limiting
						case System.Net.HttpStatusCode.BadGateway:
						case System.Net.HttpStatusCode.GatewayTimeout:
						case System.Net.HttpStatusCode.InternalServerError:
						case System.Net.HttpStatusCode.ServiceUnavailable:
							return new CloudUnavailableException( dropboxException.Message, dropboxException, dropboxException.StatusCode, isRecoverable: true );

						case System.Net.HttpStatusCode.BadRequest:
						case System.Net.HttpStatusCode.Forbidden:
						case System.Net.HttpStatusCode.HttpVersionNotSupported:
						case System.Net.HttpStatusCode.LengthRequired:
						case System.Net.HttpStatusCode.MethodNotAllowed:
						case System.Net.HttpStatusCode.NotImplemented:
							return new CloudBadRequestException( dropboxException.Message, dropboxException, dropboxException.StatusCode );

						case System.Net.HttpStatusCode.Unauthorized:
							return new CloudUnauthorizedException( dropboxException.Message, dropboxException );

						case (HttpStatusCode) 507:
							return new CloudQuotaExceededException( dropboxException.Message, dropboxException );

						case System.Net.HttpStatusCode.Accepted:
						case System.Net.HttpStatusCode.Ambiguous:
						// also System.Net.HttpStatusCode.MultipleChoices
						case System.Net.HttpStatusCode.Conflict:
						case System.Net.HttpStatusCode.Continue:
						case System.Net.HttpStatusCode.Created:
						case System.Net.HttpStatusCode.ExpectationFailed:
						case System.Net.HttpStatusCode.Found:
						// also System.Net.HttpStatusCode.Redirect
						case System.Net.HttpStatusCode.Gone:
						case System.Net.HttpStatusCode.Moved:
						// also System.Net.HttpStatusCode.MovedPermanently
						case System.Net.HttpStatusCode.NoContent:
						case System.Net.HttpStatusCode.NonAuthoritativeInformation:
						case System.Net.HttpStatusCode.NotAcceptable:
						case System.Net.HttpStatusCode.NotModified:
						case System.Net.HttpStatusCode.OK:
						case System.Net.HttpStatusCode.PartialContent:
						case System.Net.HttpStatusCode.PaymentRequired:
						case System.Net.HttpStatusCode.PreconditionFailed:
						case System.Net.HttpStatusCode.ProxyAuthenticationRequired:
						case System.Net.HttpStatusCode.RedirectKeepVerb:
						// also System.Net.HttpStatusCode.TemporaryRedirect
						case System.Net.HttpStatusCode.RedirectMethod:
						// also System.Net.HttpStatusCode.SeeOther
						case System.Net.HttpStatusCode.RequestEntityTooLarge:
						case System.Net.HttpStatusCode.RequestTimeout:
						case System.Net.HttpStatusCode.RequestUriTooLong:
						case System.Net.HttpStatusCode.RequestedRangeNotSatisfiable:
						case System.Net.HttpStatusCode.ResetContent:
						case System.Net.HttpStatusCode.SwitchingProtocols:
						case System.Net.HttpStatusCode.UnsupportedMediaType:
						case System.Net.HttpStatusCode.Unused:
						case System.Net.HttpStatusCode.UseProxy:
						default:
							return new CloudUnexpectedResponseException( dropboxException.Message, dropboxException, dropboxException.StatusCode );
					}
				}
				else if ( dropboxException.InnerException != null )
				{
					if ( dropboxException.InnerException is HttpRequestException && dropboxException.InnerException.InnerException is WebException )
					{
						// this seems to indicate no internet
						return new CloudUnavailableException( dropboxException.InnerException.InnerException.Message, dropboxException, dropboxException.StatusCode, isRecoverable: true );
					}
				}
			}
			else if ( e is FileNotFoundException )
			{
				return new CloudFileNotFoundException( e.Message, e );
			}

			return e;
		}
	}
}
